package ddz.logic;

import ch.qos.logback.classic.Logger;
import com.kaka.notice.Command;
import com.kaka.notice.Message;
import com.kaka.notice.annotation.Handler;
import ddz.constants.OpCode;
import ddz.net.CtxManager;
import ddz.net.NetOpCode;
import ddz.net.ProtocolMessage;
import ddz.net.WsSender;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * 网络处理
 *
 * @author zkpursuit
 */
@Handler(cmd = NetOpCode.CHANNEL_ACTIVE, type = String.class)
@Handler(cmd = NetOpCode.CHANNEL_REMOVE, type = String.class)
@Handler(cmd = NetOpCode.CHANNEL_EXCEPTION, type = String.class)
@Handler(cmd = NetOpCode.READER_IDLE, type = String.class)
@Handler(cmd = NetOpCode.WRITER_IDLE, type = String.class)
@Handler(cmd = NetOpCode.ALL_IDLE, type = String.class)
public class NetChannelHandler extends Command implements WsSender {

    private final Logger logger = (Logger) LoggerFactory.getLogger(NetChannelHandler.class);

    @Override
    public void execute(Message msg) {
        //logger.info(String.valueOf(cmd()));
        if (cmd().equals(NetOpCode.CHANNEL_ACTIVE)) {
            if (logger.isInfoEnabled()) logger.info("有新的连接");
        } else if (cmd().equals(NetOpCode.CHANNEL_REMOVE)) {
            ChannelHandlerContext ctx = (ChannelHandlerContext) msg.getBody();
            Object uid = CtxManager.instance().remove(ctx);
            this.remove(uid);
            if (logger.isInfoEnabled()) {
                logger.info("（" + uid + "）信道被移除  客户端总数：==>> " + CtxManager.instance().getClientCount());
            }
        } else if (cmd().equals(NetOpCode.CHANNEL_EXCEPTION)) {
            Object[] objs = (Object[]) msg.getBody();
            ChannelHandlerContext ctx = (ChannelHandlerContext) objs[0];
            Throwable cause = (Throwable) objs[1];
            if (cause instanceof IOException) {
                //客户端关闭
                logger.error(cause.getMessage());
                ctx.close();
            } else {
                logger.error(cause.getMessage(), cause);
            }
        } else if (cmd().equals(NetOpCode.READER_IDLE)) {
//            ChannelHandlerContext ctx = (ChannelHandlerContext) msg.getBody();
//            byte[] bytes = GlobalConn.ScHeartBeat.newBuilder()
//                    .setTime(System.currentTimeMillis())
//                    .build().toByteArray();
//            this.sendData(ctx, 0, Integer.parseInt(OpCode.cmd_heart_beat), bytes);
        } else if (cmd().equals(NetOpCode.WRITER_IDLE)) {
            ChannelHandlerContext ctx = (ChannelHandlerContext) msg.getBody();
            Object ctxId = CtxManager.getBindId(ctx);
            ChannelFuture cf = ctx.close();
            if (logger.isInfoEnabled()) {
                logger.info("==>>" + ctxId + "写超时，准备关闭连接！");
            }
            cf.addListener((ChannelFuture future) -> {
                //正式关闭
                if (logger.isInfoEnabled()) logger.info("==>>" + ctxId + "写超时，连接已被关闭");
            });
        } else if (cmd().equals(NetOpCode.ALL_IDLE)) {
            if (logger.isInfoEnabled()) logger.info("==>>  读写超时");
        }
    }

    protected void remove(Object client_id) {
        if (client_id == null) {
            return;
        }
        if (client_id instanceof Long) {
            long uid = (Long) client_id;
            if (uid <= 0) return;
            int exitRoomCmd = Integer.parseInt(OpCode.cmd_exit_room);
            this.sendMessage(new ProtocolMessage(exitRoomCmd, null, uid));
        }
    }

}
